#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>

#include "msocket.h"
#include "dh_net.h"

int main(int argc, char *argv[])
{

    assert(socket_init() == 0);
    socket_t sock = socket_tcp();
    assert(sock != 0);
    assert(socket_connect_ipv4(sock, "127.0.0.1", 8000) == 0);

    fd_set rfds, wfds;
    struct timeval timeout;

    char buffer[256] = {0};
    dh_net_protocol_t buf = {0};

    // 将标准输入设置为非阻塞模式
    int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    if (flags == -1)
    {
        perror("fcntl F_GETFL");
        goto exit;
    }
    flags |= O_NONBLOCK;
    if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1)
    {
        perror("fcntl F_SETFL");
        goto exit;
    }

    while (1)
    {
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        FD_SET(sock, &rfds);
        FD_SET(sock, &wfds);
        timeout = (struct timeval){
            .tv_sec = 5,
            .tv_usec = 0,
        };

        int select_ret = socket_select(sock + 1, &rfds, &wfds, NULL, &timeout);
        if (select_ret <= 0)
        {
            if (select_ret == 0)
            {
                fprintf(stdout, "socket_select() time out\n");
                continue;
            }
            else
            {
                perror("socket_select()");
                break;
            }
        }
        // 有数据可读
        if (FD_ISSET(sock, &rfds))
        {
            int ret = socket_recv(sock, &buf, sizeof(buf), MSG_WAITALL);
            if (ret <= 0)
            {
                if (ret == 0)
                    fprintf(stdout, "socket_recv() server close\n");
                else
                    perror("socket_recv()");
                break;
            }
            printf("recv bytes(%d) len(%d):%s\n", ret, strlen(buf.buf), buf.buf);
        }
        // 可写
        if (FD_ISSET(sock, &wfds))
        {
            memset(buffer, 0, sizeof(buffer));
            fgets(buffer, sizeof(buffer), stdin);
            if (strlen(buffer) == 0) // 长度为0不发送数据
                continue;
            if (strncmp(buffer, "exit", 4) == 0)
                break;

            int ret = socket_send(sock, &buf, sizeof(buf), MSG_WAITALL);
            if (ret <= 0)
            {
                perror("socket_send()");
                break;
            }
        }
    }

    // 将标准输入恢复为阻塞模式
    flags &= ~O_NONBLOCK;
    if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1)
    {
        perror("fcntl F_SETFL");
    }
exit:
    socket_close(sock);
    assert(socket_cleanup() == 0);
    return 0;
}